#!/usr/bin/env python
# coding=utf-8

"""yaml config parser"""
import copy
from pathlib import Path
from typing import Dict, List, Union

from ruamel.yaml import YAML

yaml = YAML(typ="safe", pure=True)
# yaml.default_flow_style = False


def parse_yaml_file(conf_path) -> Dict:
    """parse yaml option file with finchan options.

    return a dict with all options in it.
    """
    fpath = Path(conf_path).expanduser()
    if not fpath.exists():
        return {}
    if not fpath.is_file():
        return {}
    try:
        return yaml.load(Path(conf_path))
    except Exception as e:
        raise SyntaxError("load configure file failed: %s" % str(e))


def merge_configs(
    a: Union[Dict, List], b: Union[Dict, List], inplace=True, replace=False
) -> Union[Dict, List]:
    """deep merge dict/list configs, merge all dict&list values, recursively

    :param a: config one
    :param b: config two
    :param inplace: whether modify and merged into a
    :param replace: if a config key both in a and b, use b to replace a
    """
    if type(a) != type(b):
        raise TypeError("Different type of merge objects: %s<=>%s" % (type(a), type(b)))

    if not isinstance(a, (list, dict)):
        raise TypeError("can only merge dict/list, get %s" % type(a))

    merged_config = a
    if not inplace:
        merged_config = copy.deepcopy(a)

    if isinstance(merged_config, list):
        for val in b:
            if val not in merged_config:
                merged_config.append(val)
    else:
        for key, val in b.items():
            if key not in merged_config:
                merged_config[key] = val
                continue

            if not isinstance(merged_config[key], type(val)):
                raise TypeError(
                    "Different types for key %s found: %s<=>%s"
                    % (key, type(merged_config), type(b))
                )

            if isinstance(val, (list, dict)):
                merge_configs(merged_config[key], val)
            else:
                if replace:
                    merged_config[key] = val
                    continue
                # raise TypeError(
                #     "can only merge dict/list, get %s for key %s" % (type(val), key)
                # )
    return merged_config


def load_yml_config_path(conf_path: Union[str, Path]) -> Dict:
    """load yaml configure files from a path, support one file and multiple configure files in the path"""
    p = Path(conf_path).expanduser()
    if p.is_file():
        return parse_yaml_file(p)

    configs = [parse_yaml_file(f) for f in p.rglob("*.yml")]

    merged_config: Dict = {}
    for config in configs:
        if not config:  # skip empty configure file
            continue
        merge_configs(merged_config, config)
    return merged_config


def load_yml_config_list(*conf_files: Union[str, Path]) -> Dict:
    """加载列表中的 yaml 文件并合并"""
    configs = [load_yml_config_path(f) for f in conf_files]

    if len(configs) == 1:
        return configs[0]

    merged_config: Dict = {}
    for config in configs:
        if not config:  # skip empty configure file
            continue
        merge_configs(merged_config, config)
    return merged_config






